export {};

// 需求：定义一个泛型函数，传入两个参数：（对象，对象的key）。返回对象指定key的值。

// function getProp (obj, key){
//   return obj[key]
// }

// 1 约束为某一个具体的对象和具体的key
type Obj = {
  name: string;
  age: number;
};

type Key = 'name' | 'age';

function getProp<T extends Obj, K extends Key>(obj: T, key: K): T[K] {
  return obj[key];
}

// 测试调用
let result1 = getProp({ name: 'Jack', age: 18 }, 'name'); // 返回值类型是啥 string
let result2 = getProp({ name: 'Jack', age: 18 }, 'age'); // 返回值类型是啥 number

// 2 约束为一个具体的对象，但是key是从这个对象中动态获取的
function getProp2<T extends Obj, K extends keyof T>(obj: T, key: K): T[K] {
  return obj[key];
}

// 测试调用
let result3 = getProp2({ name: 'Jack', age: 18 }, 'name');

// 3 对象和key的类型都是动态的
// 需求：定义一个泛型函数，传入两个参数：（对象，对象的key）。返回对象指定key的值。
// 下面这个函数在 TS 中的定义
// function getProp (obj, key){
//   return obj[key]
// }
function getProp3<T extends object, K extends keyof T>(obj: T, key: K): T[K] {
  // 原生的话，这里要加好多判断代码
  return obj[key];
}

// 测试调用
console.log(getProp3({ a: 'a', b: 2 }, 'b'));

console.log(getProp3([1, 2, 3], 'length'));
console.log(getProp3([1, 2, 3], 'map').toString());
